﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Configuration;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using EKAABSInformationManagement.Database;
using EKAABSInformationManagement.Service;

namespace EKAABSInformationManagement.WindowsService
{
    public partial class AutoMail : ServiceBase
    {
        CancellationTokenSource cts;
        NetworkService nw_service;
        CardService card_service;
        BellAccount acc_service;
        string uesrName = string.Empty;
        string pwd = string.Empty;
        string serviceUri = string.Empty;
        private System.Timers.Timer time;
        public AutoMail()
        {
            nw_service = new NetworkService();
            card_service = new CardService();
            acc_service = new BellAccount();
            uesrName = ConfigurationManager.AppSettings["userName"];
            pwd = ConfigurationManager.AppSettings["password"];
            serviceUri = ConfigurationManager.AppSettings["serviceUri"];
            InitializeComponent();
        }
        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("Auto mail for EKA-ASB-IM has been started on " + System.DateTime.Now.ToString());
            int fixedInterval = default(int);
            Int32.TryParse(ConfigurationManager.AppSettings["fixedInterval"], out fixedInterval);
            if (fixedInterval == 0) fixedInterval = 2;
            time = new System.Timers.Timer(1000 * 60 * 60 * 24 * fixedInterval);
            time.Enabled = true;
            time.Elapsed += this.RunApp;
            time.Start();
        }
        protected override void OnStop()
        {
            cts.Cancel();
            time.Enabled = false;
        }
        #region network
        private void preOverDue_Network()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Network"], ConfigurationManager.AppSettings["fixedOverDueUnit_Network"]);
                DateTime preOverDueDate = this.getDateByCustomerConfig(overDueDate, ConfigurationManager.AppSettings["fixedPreOverDue"], ConfigurationManager.AppSettings["fixedPreOverDueUnit"]);
                List<network> preOverDue_nw = nw_service.getPreOverdueNWInfo_By_Fixeddate(overDueDate, preOverDueDate);
                Parallel.For(0, preOverDue_nw.Count, (i) =>
                {
                    nw_service.update_NetworkStatus_By_MAC(preOverDue_nw[i].MAC, 2);
                    networkInfo_mail mailInfo = nw_service.getNetworkInfoForMail_By_MAC(preOverDue_nw[i].MAC);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的一个网络（资产ID：", mailInfo.assetID, ",MAC:" + mailInfo.MAC, "）即将过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "网络状态即将过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing preOverDue_Network, error message:" + ex.Message);
            }
        }
        private void overDued_Network()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Network"], ConfigurationManager.AppSettings["fixedOverDueUnit_Network"]);
                List<network> OverDue_nw = nw_service.getOverduedNWInfo_By_Fixeddate(overDueDate);
                Parallel.For(0, OverDue_nw.Count, (i) =>
                {
                    nw_service.update_NetworkStatus_By_MAC(OverDue_nw[i].MAC, 3);
                    networkInfo_mail mailInfo = nw_service.getNetworkInfoForMail_By_MAC(OverDue_nw[i].MAC);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的一个网络（资产ID：", mailInfo.assetID, ",MAC:" + mailInfo.MAC, "）已经过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "网络状态已经过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing OverDued_Network, error message:" + ex.Message);
            }
        }
        #endregion
        #region Bell account
        private void preOverDue_Acc()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Acc"], ConfigurationManager.AppSettings["fixedOverDueUnit_Acc"]);
                DateTime preOverDueDate = this.getDateByCustomerConfig(overDueDate, ConfigurationManager.AppSettings["fixedPreOverDue"], ConfigurationManager.AppSettings["fixedPreOverDueUnit"]);
                List<accountInBell> preOverDue_acc = acc_service.getPreOverdueAccInfo_By_Fixeddate(overDueDate, preOverDueDate);
                Parallel.For(0, preOverDue_acc.Count, (i) =>
                {
                    acc_service.update_AccStatus_By_AccID(preOverDue_acc[i].accountID, 2);
                    BellAccountInfo_mail mailInfo = acc_service.getAccInfoForMail_By_ID(preOverDue_acc[i].accountID);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的贝尔账号（ID：", mailInfo.AccID, ",贝尔工号:" + mailInfo.AccID2, "）即将过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "贝尔账号即将过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing preOverDue_Acc, error message:" + ex.Message);
            }
        }
        private void overDued_Acc()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Acc"], ConfigurationManager.AppSettings["fixedOverDueUnit_Acc"]);
                List<accountInBell> OverDue_acc = acc_service.getOverduedAccInfo_By_Fixeddate(overDueDate);
                Parallel.For(0, OverDue_acc.Count, (i) =>
                {
                    acc_service.update_AccStatus_By_AccID(OverDue_acc[i].accountID, 3);
                    BellAccountInfo_mail mailInfo = acc_service.getAccInfoForMail_By_ID(OverDue_acc[i].accountID);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的贝尔账号（ID：", mailInfo.AccID, ",贝尔工号:" + mailInfo.AccID2, "）已经过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "贝尔账号已经过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing OverDued_Acc, error message:" + ex.Message);
            }
        }
        #endregion
        #region Bell card
        private void preOverDue_card()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Card"], ConfigurationManager.AppSettings["fixedOverDueUnit_Card"]);
                DateTime preOverDueDate = this.getDateByCustomerConfig(overDueDate, ConfigurationManager.AppSettings["fixedPreOverDue"], ConfigurationManager.AppSettings["fixedPreOverDueUnit"]);
                List<cardInBell> preOverDue_card = card_service.getPreOverdueCardInfo_By_Fixeddate(overDueDate, preOverDueDate);
                Parallel.For(0, preOverDue_card.Count, (i) =>
                {
                    card_service.update_CardStatus_By_ID(preOverDue_card[i].cardNo, 2);
                    BellCard_mail mailInfo = card_service.getCardInfoForMail_By_ID(preOverDue_card[i].cardNo);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的贝尔磁卡（ID：", mailInfo.BellCardID, "）即将过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "贝尔磁即将过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing preOverDue_Network, error message:" + ex.Message);
            }
        }
        private void overDued_card()
        {
            try
            {
                DateTime overDueDate = this.getDateByCustomerConfig(DateTime.Now, ConfigurationManager.AppSettings["fixedOverDue_Card"], ConfigurationManager.AppSettings["fixedOverDueUnit_Card"]);
                List<cardInBell> OverDue_card = card_service.getOverduedCardInfo_By_Fixeddate(overDueDate);
                Parallel.For(0, OverDue_card.Count, (i) =>
                {
                    card_service.update_CardStatus_By_ID(OverDue_card[i].cardNo, 3);
                    BellCard_mail mailInfo = card_service.getCardInfoForMail_By_ID(OverDue_card[i].cardNo);
                    string mailBody = string.Concat("Hi ", mailInfo.owner, ",\r\n\r\n你的贝尔磁卡（ID：", mailInfo.BellCardID, "）已经过期，请联系PA。\r\n\r\nRegards,\r\nPA");
                    mailService.sendMail(uesrName, pwd, serviceUri, "贝尔磁已经过期", mailBody, mailInfo.owner, string.Empty);
                });
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error occured on " + System.DateTime.Now.ToString() + " while procesing preOverDue_Network, error message:" + ex.Message);
            }
        }
        #endregion
        private DateTime getDateByCustomerConfig(DateTime dt, string value, string unit)
        {
            DateTime reslut = default(DateTime);
            int val = default(int);
            Int32.TryParse(value, out val);
            if (val == 0)
            {
                eventLog1.WriteEntry("Value for 'fixedOverDue' is not a number!", EventLogEntryType.Error);
                cts.Cancel();
            }
            switch (unit)
            {
                case "day":
                    reslut = dt.AddDays(-val);
                    break;
                case "week":
                    reslut = dt.AddDays(-val * 7);
                    break;
                case "month":
                    reslut = dt.AddMonths(-val);
                    break;
                case "year":
                    reslut = dt.AddYears(-val);
                    break;
                default:
                    eventLog1.WriteEntry("Value for 'fixedOverDueUnit' is invalidated!", EventLogEntryType.Error);
                    cts.Cancel();
                    break;
            }
            return reslut;
        }
        private void RunApp(object sender, EventArgs e)
        {
            int maxDegreeOfParallelism = default(int);
            Int32.TryParse(ConfigurationManager.AppSettings["MaxDegreeOfParallelism"], out maxDegreeOfParallelism);
            if (maxDegreeOfParallelism == 0) maxDegreeOfParallelism = 10;
            cts = new CancellationTokenSource();
            ParallelOptions pOption = new ParallelOptions() { CancellationToken = cts.Token };
            pOption.MaxDegreeOfParallelism = maxDegreeOfParallelism;
            Task tasks = new Task(() =>
            {
                Task.Factory.StartNew(() => preOverDue_Network());
                Task.Factory.StartNew(() => overDued_Network());
                Task.Factory.StartNew(() => preOverDue_Acc());
                Task.Factory.StartNew(() => overDued_Acc());
                Task.Factory.StartNew(() => preOverDue_card());
                Task.Factory.StartNew(() => overDued_card());
            }, cts.Token);
            tasks.Start();
            eventLog1.WriteEntry("Auto mail for EKA-ASB-IM is now in processing...");
            tasks.Wait();
            if (cts.IsCancellationRequested)
            {
                eventLog1.WriteEntry("Auto mail for EKA-ASB-IM has been canceled on " + System.DateTime.Now.ToString());
            }
            else
            {
                eventLog1.WriteEntry("Auto mail for EKA-ASB-IM has finished on " + System.DateTime.Now.ToString());
            }
        }
    }
}
